import {
  forwardRef,
  HttpException,
  HttpStatus,
  Inject,
  Injectable,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Friend } from 'src/entities/friend.entity';
import { Message } from 'src/entities/message.entity';
import { User } from 'src/entities/user.entity';
import { UserMessage } from 'src/entities/userMessage.entity';
import { SocketService } from 'src/socket/socket.service';
import { UserService } from 'src/user/user.service';
import { Repository } from 'typeorm';
import { MessageUserDto } from './dto/messageUser.dto';
import { SendMessage } from './dto/sendMessage.dto';

@Injectable()
export class UserMessageService {
  constructor(
    @Inject(forwardRef(() => SocketService))
    private readonly socketService: SocketService,
    private readonly userService: UserService,
    @InjectRepository(Friend)
    private friendRepository: Repository<Friend>,
    @InjectRepository(Message)
    private messagesRepository: Repository<Message>,
    @InjectRepository(UserMessage)
    private userMessagesRepository: Repository<UserMessage>,
  ) {}

  async sendMessage(data: SendMessage) {
    let friend = await this.friendRepository.findOne({
      where: {
        userId: data.sendUserId,
        friendId: data.onUserId,
        isDel: 0,
      },
    });
    if (!friend) {
      throw new HttpException('您未添加对方为好友', HttpStatus.BAD_REQUEST);
    }
    let messageResult = await this.messagesRepository.save({
      context: data.context,
      type: data.type,
    });
    let result = await this.userMessagesRepository.save({
      messageId: messageResult.id,
      sendUserId: data.sendUserId,
      onUserId: data.onUserId,
      isRead: 0,
    });
    let user: User = await this.userService.findOne(data.sendUserId);

    this.socketService.sendNewMessage(data.onUserId, user, {
      context: messageResult.context,
      type: messageResult.type,
      createdTime: result.createdTime,
      sendUserId: result.sendUserId,
    });
  }

  async getUserMessageList(userId: string, friendId: string) {
    let user = await this.userService.findOne(friendId);
    let messages = await this.userMessagesRepository
      .createQueryBuilder('userMessage')
      .where(
        '(userMessage.sendUserId=:userId&&userMessage.onUserId=:friendId )||(userMessage.sendUserId=:friendId&&userMessage.onUserId=:userId)',
        {
          userId,
          friendId,
        },
      )
      .addOrderBy('userMessage.createdTime', 'ASC')
      .leftJoinAndMapOne(
        'userMessage.message',
        Message,
        'message',
        'userMessage.messageId=message.id',
      )
      .select([
        'message.context as context',
        'message.type as type',
        'message.createdTime as createdTime',
        'userMessage.sendUserId as sendUserId',
      ])
      .getRawMany();
    let messagesList = messages.filter((item) => {
      if (
        item.type != 'system' ||
        (item.type == 'system' && item.sendUserId != userId)
      )
        return item;
    });
    return { friend: user, messages: messagesList };
  }

  async getMessageUserList(userId: string) {
    let messageUserList: MessageUserDto[] = [];
    let data = await this.friendRepository.find({
      where: { isMessage: 0, userId },
    });
    let numList = [];
    for (let item of data) {
      let result = await this.userMessagesRepository.findOne({
        where: [
          {
            sendUserId: item.userId,
            onUserId: item.friendId,
          },
          {
            sendUserId: item.friendId,
            onUserId: item.userId,
          },
        ],
        order: { createdTime: 'desc' },
      });

      if (!result) break;
      let message = await this.messagesRepository.findOne({
        where: { id: result.messageId },
      });
      let userMessage = await this.userMessagesRepository.find({
        where: {
          sendUserId: item.friendId,
          isRead: 0,
        },
      });
      if (!userMessage) break;
      numList.push(message.createdTime.getTime());
      let user = await this.userService.findOne(item.friendId);
      messageUserList.push({
        user,
        message,
        isWei: userMessage.length,
      });
    }
    let list: MessageUserDto[] = [];
    let newNumList = JSON.parse(JSON.stringify(numList.sort((a, b) => b - a)));
    list = newNumList.map((val) => {
      return messageUserList.find(
        (item) => item.message.createdTime.getTime() == val,
      );
    });
    return list;
  }
}
